<?php

Loader::using("underscore::libs::Plexus::Plexus");

/**
 * Allows a plugin to chnge the execution flow of a module by deciding if module
 * can run or not.
 */
interface BeforeTask {

    /**
     * Implementor must say if the current task can be executed.
     * 
     * @param string $task The task that is about to be executed.
     * 
     * @return boolean True if task can be executed, false otherwise.
     */
    function beforeTask($task);
}

/**
 * Allows changing the result of a task execution by allowing the edition
 * of the render result.
 */
interface AfterTask {

    /**
     * Allows a method to change the result of a module's output.
     * 
     * @param string $task The name of the task that has been executed.
     * @param string $htmlResult The HTML output of the executed task.
     */
    function afterTask($task, &$htmlResult);
}

/**
 * These plugins may replace the task result. If willReplaceTask returns true
 * the execution of the task is avoided and the plugin gets the responsibility
 * of returning the result that the task would have returned.
 */
interface ReplaceTask {
    /**
     * Tell if wether or not the plugin will replace the task.
     * 
     * @param string $task The task to be replaced.
     */
    function willReplaceTask($task);
    /**
     * Do the task replacement.
     */
    function replaceTask();
}

/**
 * <p>Serves as a Base class for all underscore plugins thus all underscore plugin
 * must acomplish these conditions:</p>
 * 
 * <ul>
 *  <li>Extend this class</li>
 *  <li>Implement one or more of the interfaces asociated to this class.</li>
 *  <li>Be annotated with <code>@export Plugins</code></li>
 * </ul>
 *
 * @author JeyDotC
 * 
 * @see BeforeTask
 * @see AfterTask
 * @see ReplaceTask
 */
abstract class UnderscorePlugin extends Plugin {

    public final function aroundModuleExecute($task) {
        $result = true;

        if ($this instanceof BeforeTask) {
            $result = (boolean)$this->beforeTask($task);
        }
        
        if($result && $this instanceof ReplaceTask && $this->willReplaceTask($task)){
            $result = $this->replaceTask();
        }

        return $result;
    }

    public final function onModuleExecute($task, &$result) {
        if ($this instanceof AfterTask) {
            $this->afterTask($task, $result);
        }
    }

    /**
     *
     * @return Module
     */
    protected final function getModule() {
        return $this->baseObject;
    }

}

?>
